package com.bos.prop.controller;

import com.bos.dao.KabupatenDAO;
import com.bos.dao.KecamatanDAO;
import com.bos.dao.KelurahanDAO;
import com.bos.domain.Kabupaten;
import com.bos.domain.Kecamatan;
import com.bos.domain.Kelurahan;
import com.bos.editor.KabupatenEditor;
import com.bos.editor.KecamatanEditor;
import com.bos.editor.KelurahanEditor;
import com.bos.util.UrlUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import javax.validation.Valid;
import java.util.List;
import java.util.Map;

/**
 * Created by IntelliJ IDEA.
 * User: Latief
 * Date: 3/18/11
 * Time: 3:06 PM
 * To change this template use File | Settings | File Templates.
 */
@Controller
public class KelurahanController {

    private KelurahanDAO kelurahanDAO;
    private KecamatanDAO kecamatanDAO;
    private KabupatenDAO kabupatenDAO;
    private RestTemplate restTemplate;
    /*private Credentials credentials;*/


    /* --------------------- Getter and Setter ---------------------*/

    /*public Credentials getCredentials() {
        return credentials;
    }

    @Autowired
    public void setCredentials(Credentials credentials) {
        this.credentials = credentials;
        if (restTemplate != null) {
            CommonsClientHttpRequestFactory factory = (CommonsClientHttpRequestFactory) restTemplate.getRequestFactory();
            HttpClient client = factory.getHttpClient();
            client.getState().setCredentials(AuthScope.ANY, credentials);
        }
    }*/

    @Autowired
    public void setRestTemplate(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;

//        if (credentials != null) {
//            CommonsClientHttpRequestFactory factory = (CommonsClientHttpRequestFactory) restTemplate.getRequestFactory();
//            HttpClient client = factory.getHttpClient();
//            client.getState().setCredentials(AuthScope.ANY, credentials);
//        }
    }

    @Autowired
    public void setKecamatanDAO(KecamatanDAO kecamatanDAO) {
        this.kecamatanDAO = kecamatanDAO;
    }

    @Autowired
    public void setKabupatenDAO(KabupatenDAO kabupatenDAO) {
        this.kabupatenDAO = kabupatenDAO;
    }

    @Autowired
    public void setKelurahanDAO(KelurahanDAO kelurahanDAO) {
        this.kelurahanDAO = kelurahanDAO;
    }

    /* -------------------------- Other Methods -------------------------- */

    @RequestMapping(value = "/kelurahan", method = RequestMethod.GET)
    public String index(ModelMap modelMap) {
        modelMap.addAttribute("kabMenuList", kabupatenDAO.getAll());
        modelMap.addAttribute("data", kelurahanDAO.getAll());

        return "kelurahan/index";
    }

    @RequestMapping(value = "/kelurahan/new", method = RequestMethod.GET)
    public String create(ModelMap modelMap) {
        Kelurahan kelurahan = new Kelurahan();
        modelMap.addAttribute("kelurahan", kelurahan);
        modelMap.addAttribute("kabMenuList", kabupatenDAO.getAll());
        modelMap.addAttribute("kabupatenList", kabupatenDAO.getAll());

        return "kelurahan/create";
    }

    @RequestMapping(value = "/kelurahan", method = RequestMethod.POST)
    public String save(@Valid @ModelAttribute("kelurahan") Kelurahan kelurahan, BindingResult result, ModelMap modelMap) {
        List<Kabupaten> kabupatens = kabupatenDAO.getAll();
        modelMap.addAttribute("kabMenuList", kabupatens);

        if (kelurahan == null) throw new IllegalArgumentException("A Product is required");
        if (result.hasErrors() || !UrlUtil.isHostsAvailable(kabupatens)) {
            modelMap.addAttribute("kelurahan", kelurahan);
            modelMap.addAttribute("kabupatenList", kabupatenDAO.getAll());

            return "kelurahan/create";
        }

        //simpan ke database lokal
        kelurahanDAO.save(kelurahan);

        //Siapkan data baru yang akan dikirim ke semua host
        String restError = "";
        Kelurahan kelurahanHttpEntity = new Kelurahan();
        kelurahanHttpEntity.setNama(kelurahan.getNama());
        kelurahanHttpEntity.setKecamatan(kelurahan.getKecamatan());
        HttpEntity<Kelurahan> httpEntity = new HttpEntity<Kelurahan>(kelurahanHttpEntity);

        //Kirim data baru dengan json ke semua host.
        List<Kabupaten> hosts = kabupatenDAO.getAll();
        for (Kabupaten host : hosts) {
            String hostUrl = UrlUtil.getKabupatenHostUrl(host) + "/kelurahan.json";
            try {
                ResponseEntity<Map> responseEntity = restTemplate.exchange(hostUrl, HttpMethod.POST, httpEntity, Map.class);
                Map<String, Object> response = responseEntity.getBody();
                if (!(Boolean) response.get("success"))
                    restError += hostUrl + "\n";
            } catch (Exception e) {
                e.printStackTrace();
                restError += hostUrl + "\n";
            }
        }
        //atribute jika terjadi error saat melakukan penyimpanan ke database kabupaten.
        if (!restError.isEmpty())
            modelMap.addAttribute("restError", restError.trim());

        return "redirect:/kelurahan/" + kelurahan.getId();
    }

    @RequestMapping(value = "/kelurahan/{id}", method = RequestMethod.GET)
    public String show(ModelMap modelMap, @PathVariable("id") Kelurahan kelurahan) {
        modelMap.addAttribute("kabMenuList", kabupatenDAO.getAll());
        modelMap.addAttribute("data", kelurahan);

        return "kelurahan/show";
    }

    @RequestMapping(value = "/kelurahan/{id}/delete", method = RequestMethod.GET)
    public String delete(ModelMap modelMap, @PathVariable("id") Kelurahan kelurahan) {
        List<Kabupaten> kabupatens = kabupatenDAO.getAll();
        modelMap.addAttribute("kabMenuList", kabupatens);

        //Jika ada host yang tidak ada maka skip operasi
        if (!UrlUtil.isHostsAvailable(kabupatens))
            return "redirect:/bank";

        //Siapkan data yang akan dihapus ke semua host
        String restError = "";
        HttpEntity<Kelurahan> httpEntity = new HttpEntity<Kelurahan>(kelurahan);

        //Kirim data yang akan dihapus dengan json ke semua host.
        List<Kabupaten> hosts = kabupatenDAO.getAll();
        for (Kabupaten host : hosts) {
            String hostUrl = UrlUtil.getKabupatenHostUrl(host) + "/kelurahan/" + kelurahan.getId() + "/delete.json";
            try {
                ResponseEntity<Map> responseEntity = restTemplate.exchange(hostUrl, HttpMethod.GET, httpEntity, Map.class);
                Map<String, Object> response = responseEntity.getBody();
                if (!(Boolean) response.get("success"))
                    restError += hostUrl + "\n";
            } catch (Exception e) {
                e.printStackTrace();
                restError += hostUrl + "\n";
            }
        }
        //atribute jika terjadi error saat melakukan penghapusan data di tiap host.
        if (!restError.isEmpty())
            modelMap.addAttribute("restError", restError.trim());

        //Hapus data lokal setelahnya.
        kelurahanDAO.delete(kelurahan);

        return "redirect:/kelurahan";
    }


    @RequestMapping(value = "/kelurahan/{id}/edit", method = RequestMethod.GET)
    public String edit(ModelMap modelMap, @PathVariable("id") Kelurahan kelurahan) {
        modelMap.addAttribute("kabMenuList", kabupatenDAO.getAll());
        modelMap.addAttribute("kelurahan", kelurahan);
        modelMap.addAttribute("kecamatanList", kecamatanDAO.getByKabupaten(kelurahan.getKecamatan().getKabupaten()));
        modelMap.addAttribute("kabupatenList", kabupatenDAO.getAll());

        return "kelurahan/edit";
    }

    @RequestMapping(value = "/kelurahan", method = RequestMethod.PUT)
    public String update(@Valid @ModelAttribute("kelurahan") Kelurahan kelurahan, BindingResult result, ModelMap modelMap) {
        List<Kabupaten> kabupatens = kabupatenDAO.getAll();
        modelMap.addAttribute("kabMenuList", kabupatens);

        if (kelurahan == null) throw new IllegalArgumentException("A Product is required");
        if (result.hasErrors() || !UrlUtil.isHostsAvailable(kabupatens)) {
            modelMap.addAttribute("kelurahan", kelurahan);
            modelMap.addAttribute("kecamatanList", kecamatanDAO.getByKabupaten(kelurahan.getKecamatan().getKabupaten()));
            modelMap.addAttribute("kabupatenList", kabupatenDAO.getAll());
            return "kelurahan/edit";
        }

        //Siapkan data baru yang akan dikirim ke semua host
        String restError = "";
        HttpEntity<Kelurahan> httpEntity = new HttpEntity<Kelurahan>(kelurahan);

        //Kirim data baru dengan json ke semua host.
        List<Kabupaten> hosts = kabupatenDAO.getAll();
        for (Kabupaten host : hosts) {
            String hostUrl = UrlUtil.getKabupatenHostUrl(host) + "/kelurahan.json";
            try {
                ResponseEntity<Map> responseEntity = restTemplate.exchange(hostUrl, HttpMethod.PUT, httpEntity, Map.class);
                Map<String, Object> response = responseEntity.getBody();
                if (!(Boolean) response.get("success"))
                    restError += hostUrl + "\n";
            } catch (Exception e) {
                e.printStackTrace();
                restError += hostUrl + "\n";
            }
        }

        //atribute jika terjadi error saat melakukan penyimpanan ke database kabupaten.
        if (!restError.isEmpty())
            modelMap.addAttribute("restError", restError.trim());

        //simpan ke database lokal setelah semua database di semua host lain dirubah.
        kelurahanDAO.merge(kelurahan);

        return "redirect:/kelurahan/" + kelurahan.getId();
    }

    @InitBinder
    protected void initBinder(WebDataBinder binder) throws Exception {
        binder.registerCustomEditor(Kabupaten.class, new KabupatenEditor(kabupatenDAO));
        binder.registerCustomEditor(Kecamatan.class, new KecamatanEditor(kecamatanDAO));
        binder.registerCustomEditor(Kelurahan.class, new KelurahanEditor(kelurahanDAO));
    }

}
